package com.i2863.receiptinterface.util;


import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import org.apache.http.Consts;
import org.apache.http.HttpHost;
import org.apache.http.HttpResponse;
import org.apache.http.client.CookieStore;
import org.apache.http.client.HttpClient;
import org.apache.http.client.config.CookieSpecs;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.utils.URLEncodedUtils;
import org.apache.http.config.Registry;
import org.apache.http.config.RegistryBuilder;
import org.apache.http.conn.socket.ConnectionSocketFactory;
import org.apache.http.conn.socket.PlainConnectionSocketFactory;
import org.apache.http.conn.ssl.NoopHostnameVerifier;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.impl.client.BasicCookieStore;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.protocol.HTTP;
import org.apache.http.util.EntityUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManager;
import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.util.*;

/**
 * User: ysw
 * Date: 13-12-19
 * Time: 下午2:53
 */
public class HttpSessionUtils {
    private static Logger log = LoggerFactory.getLogger(HttpSessionUtils.class);

    public static String USER_AGENT = "Mozilla/5.0 (Windows NT 6.2; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/31.0.1650.63 Safari/537.36";

    public static CloseableHttpClient buildHttpClient() {
        RequestConfig requestConfig = RequestConfig.custom().setCookieSpec(CookieSpecs.STANDARD).setConnectTimeout(50000)
                .setSocketTimeout(50000).setConnectionRequestTimeout(50000).build();
        PoolingHttpClientConnectionManager conMgr = new PoolingHttpClientConnectionManager();
        conMgr.setDefaultMaxPerRoute(20);
        conMgr.setMaxTotal(100);
        CookieStore cookieStore = new BasicCookieStore();
        return HttpClients.custom().setRetryHandler(new NoRetryHttpRequestRetryHandler()).setDefaultRequestConfig(requestConfig).setConnectionManager(conMgr).setDefaultCookieStore(cookieStore).build();
    }

    public static CloseableHttpClient buildHttpClient(HttpHost proxy) {
        RequestConfig requestConfig = RequestConfig.custom().setCookieSpec(CookieSpecs.STANDARD).setConnectTimeout(50000)
                .setSocketTimeout(50000).setConnectionRequestTimeout(50000).build();
        PoolingHttpClientConnectionManager conMgr = new PoolingHttpClientConnectionManager();
        conMgr.setDefaultMaxPerRoute(20);
        conMgr.setMaxTotal(100);
        CookieStore cookieStore = new BasicCookieStore();
        return HttpClients.custom().setRetryHandler(new NoRetryHttpRequestRetryHandler()).setProxy(proxy).setDefaultRequestConfig(requestConfig).setConnectionManager(conMgr).setDefaultCookieStore(cookieStore).build();
    }

    public static CloseableHttpClient buildHttpsClient() {
        RequestConfig requestConfig = RequestConfig.custom().setCookieSpec(CookieSpecs.STANDARD).setConnectTimeout(50000)
                .setSocketTimeout(50000).setConnectionRequestTimeout(50000).build();
        CookieStore cookieStore = new BasicCookieStore();
        //支持HTTPS
        SSLContext sslContext = null;
        try {
            sslContext = SSLContext.getInstance("TLS");
            MyX509TrustManager tm = new MyX509TrustManager();
            sslContext.init(null, new TrustManager[]{tm},
                    null);
        } catch (Exception e) {
            throw new RuntimeException();

        }

        SSLConnectionSocketFactory socketFactory = new SSLConnectionSocketFactory(sslContext, NoopHostnameVerifier.INSTANCE);
        Registry<ConnectionSocketFactory> socketFactoryRegistry = RegistryBuilder.<ConnectionSocketFactory>create().register("http", PlainConnectionSocketFactory.INSTANCE).register("https", socketFactory).build();
        PoolingHttpClientConnectionManager connectionManager = new PoolingHttpClientConnectionManager(socketFactoryRegistry);
        connectionManager.setDefaultMaxPerRoute(20);
        connectionManager.setMaxTotal(100);
        return HttpClients.custom().setRetryHandler(new NoRetryHttpRequestRetryHandler()).setDefaultRequestConfig(requestConfig).setConnectionManager(connectionManager).setDefaultCookieStore(cookieStore).build();
    }

    public static CloseableHttpClient buildHttpsClient(HttpHost proxy) {
        RequestConfig requestConfig = RequestConfig.custom().setCookieSpec(CookieSpecs.STANDARD).setConnectTimeout(50000)
                .setSocketTimeout(50000).setConnectionRequestTimeout(50000).build();
        CookieStore cookieStore = new BasicCookieStore();
        //支持HTTPS
        SSLContext sslContext = null;
        try {
            sslContext = SSLContext.getInstance("TLS");
            MyX509TrustManager tm = new MyX509TrustManager();
            sslContext.init(null, new TrustManager[]{tm},
                    null);
        } catch (Exception e) {
            throw new RuntimeException();

        }

        SSLConnectionSocketFactory socketFactory = new SSLConnectionSocketFactory(sslContext, NoopHostnameVerifier.INSTANCE);
        Registry<ConnectionSocketFactory> socketFactoryRegistry = RegistryBuilder.<ConnectionSocketFactory>create().register("http", PlainConnectionSocketFactory.INSTANCE).register("https", socketFactory).build();
        PoolingHttpClientConnectionManager connectionManager = new PoolingHttpClientConnectionManager(socketFactoryRegistry);
        connectionManager.setDefaultMaxPerRoute(20);
        connectionManager.setMaxTotal(100);
        return HttpClients.custom().setRetryHandler(new NoRetryHttpRequestRetryHandler()).setProxy(proxy).setDefaultRequestConfig(requestConfig).setConnectionManager(connectionManager).setDefaultCookieStore(cookieStore).build();
    }


    public static UrlEncodedFormEntity httpPostParameters(Map<String, String> map) {
        List<BasicNameValuePair> params = new ArrayList<BasicNameValuePair>();
        Set<String> keys = map.keySet();
        Iterator iterator = keys.iterator();
        while (iterator.hasNext()) {
            String name = (String) iterator.next();
            String value = map.get(name);
            BasicNameValuePair nameValuePair = new BasicNameValuePair(name, value);
            params.add(nameValuePair);
        }
        try {
            return new UrlEncodedFormEntity(params, HTTP.UTF_8);
        } catch (UnsupportedEncodingException e) {
            throw new RuntimeException("httpPostParameters  error", e);
        }
    }

    public static String httpGetUrl(String url, Map<String, String> map) {
        List<BasicNameValuePair> params = new ArrayList<BasicNameValuePair>();
        Set<String> keys = map.keySet();
        Iterator iterator = keys.iterator();
        while (iterator.hasNext()) {
            String name = (String) iterator.next();
            Object value = map.get(name);
            BasicNameValuePair nameValuePair = new BasicNameValuePair(name, value.toString());
            params.add(nameValuePair);
        }
        String queryString = URLEncodedUtils.format(params, Consts.UTF_8);
        return url + "?" + queryString;
    }


    public static String httpPost(HttpClient httpClient, String url, Map<String, String> map) throws IOException {
        return httpPost(httpClient, url, map, "utf-8");
    }

    public static String httpPost(HttpClient httpClient, String url, Map<String, String> map, String charset) throws IOException {
        String result = "";
        HttpPost post = new HttpPost(url);
        post.setEntity(httpPostParameters(map));
        post.setHeader(HTTP.USER_AGENT, USER_AGENT);
        HttpResponse response = httpClient.execute(post);
        result = EntityUtils.toString(response.getEntity(), charset);
        return result;
    }


    public static String httpPost(HttpClient httpClient, String url, Map<String, String> map, Map<String, String> head, String charset) throws IOException {
        String result = "";
        HttpPost post = new HttpPost(url);
        post.setEntity(httpPostParameters(map));
        post.setHeader(HTTP.USER_AGENT, USER_AGENT);
        Iterator<Map.Entry<String, String>> iter = head.entrySet().iterator();
        while (iter.hasNext()) {
            Map.Entry<String, String> entry = iter.next();
            post.setHeader(entry.getKey(), entry.getValue());
        }
        HttpResponse response = httpClient.execute(post);
        result = EntityUtils.toString(response.getEntity(), charset);
        return result;
    }

    public static HttpResponse httpPostHeaders(HttpClient httpClient, String url, Map<String, String> map, String charset) {
        int codeStatus = 500;
        String result = "";
        HttpResponse response = null;
        try {
            HttpPost post = new HttpPost(url);
            post.setEntity(httpPostParameters(map));
            post.setHeader(HTTP.USER_AGENT, USER_AGENT);
            response = httpClient.execute(post);
            codeStatus = response.getStatusLine().getStatusCode();
        } catch (IOException e) {
            e.printStackTrace();
            log.info("请求URL失败:" + url + "  code:" + codeStatus);
        }
        return response;
    }

    public static String httpGet(CloseableHttpClient httpClient, String url, Map<String, String> map, String charset) {
        int codeStatus = 500;
        String result = "";
        try {
            String _url = httpGetUrl(url, map);
            HttpGet get = new HttpGet(_url);
            get.setHeader(HTTP.USER_AGENT, USER_AGENT);
            CloseableHttpResponse response = httpClient.execute(get);
            codeStatus = response.getStatusLine().getStatusCode();
            result = EntityUtils.toString(response.getEntity(), charset);
        } catch (IOException e) {
            log.info("请求URL失败:" + url + "  code:" + codeStatus);
        }
        return result;
    }

    public static String httpGet(CloseableHttpClient httpClient, String url, Map<String, String> map) {
        return httpGet(httpClient, url, map, "UTF-8");
    }

    public static byte[] httpGetByte(CloseableHttpClient httpClient, String url) {
        int codeStatus = 0;
        byte[] bytes = null;
        try {
            HttpGet get = new HttpGet(url);
            get.setHeader(HTTP.USER_AGENT, USER_AGENT);
            CloseableHttpResponse response = httpClient.execute(get);
            codeStatus = response.getStatusLine().getStatusCode();
            bytes = EntityUtils.toByteArray(response.getEntity());
        } catch (IOException e) {
            log.info("请求URL失败:" + url + "  code:" + codeStatus);
        }
        return bytes;
    }

    public static String httpGet(HttpClient httpClient, String url) {
        return httpGet(httpClient, url, HTTP.UTF_8);
    }

    public static String httpGet(HttpClient httpClient, String url, String charset) {
        int codeStatus = 500;
        String result = "";
        HttpGet get = null;
        try {
            get = new HttpGet(url);
            get.setHeader("Connection", "close");
            get.setHeader(HTTP.USER_AGENT, USER_AGENT);
            HttpResponse response = httpClient.execute( get);
            codeStatus = response.getStatusLine().getStatusCode();
            result = EntityUtils.toString(response.getEntity(), charset);
        } catch (IOException e) {
//            log.info("请求URL失败:"+url + "  code:" +codeStatus);
            throw new RuntimeException(e);
        } finally {
            if (get != null) {
                try {
                    get.releaseConnection();
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }

        }
        return result;
    }

    public static InputStream httpContent(CloseableHttpClient httpClient, String url) {
        int codeStatus = 500;
        InputStream inputStream = null;
        try {
            HttpGet get = new HttpGet(url);
            get.setHeader(HTTP.USER_AGENT, USER_AGENT);
            CloseableHttpResponse response = httpClient.execute(get);
            codeStatus = response.getStatusLine().getStatusCode();
            inputStream = response.getEntity().getContent();
        } catch (IOException e) {
            log.info("请求URL失败:" + url + "  code:" + codeStatus);
        }
        return inputStream;
    }


    /**
     * 关闭连接池
     *
     * @param client 连接池
     */
    public static void close(CloseableHttpClient client) {
        if (client != null) {
            try {
                client.close();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

    public static void main(String[] args) throws IOException {
        CloseableHttpClient httpClient = buildHttpsClient();
        Map<String,String> map = new HashMap<String,String>();
        map.put("js_code","0234VR282TQG0R0BST182EvZ2824VR2Z");
        map.put("appid","wx190b3585df29424e");
        map.put("secret","62d54643b12cf526f51f42eeceaf3c73");
        map.put("grant_type","authorization_code");
        String html = httpPost(httpClient,"https://api.weixin.qq.com/sns/jscode2session",map);
        JSONObject jsonObject = JSON.parseObject(html);
        System.out.println(html);
        System.out.println(jsonObject.getString("session_key"));
    }

}
